"""
主窗口框架类，负责创建基本窗口结构和选项卡
"""
import sys
from PyQt5.QtWidgets import (
    QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QSplitter, 
    QTabWidget, QMessageBox, QApplication, QDialog
)
from PyQt5.QtCore import Qt, QTimer, QThread, pyqtSignal, QRunnable, QThreadPool, QObject
from PyQt5.QtGui import QFont, QIcon
import time
from datetime import datetime

from app.ui.windows.control_panel import ControlPanel
from app.ui.windows.config_panel import ConfigPanel
from app.ui.windows.channel_panel import ChannelPanel
from app.ui.theme import Theme
from app.controllers.websocket_controller import WebSocketController
from app.services.service_locator import ServiceLocator
from app.utils.logger import Logger
from app.services.audio_service import IAudioService
from app.services.ai_service import IAIService
from app.ui.components.toast import show_toast, Toast
from app.services.config_service import IConfigService
from app.services.speech_service import ISpeechService

class ServiceInitSignals(QObject):
    """
    服务初始化信号类，用于从QRunnable发送信号
    """
    websocket_started = pyqtSignal(bool, int)  # WebSocket服务器启动结果信号
    audio_service_started = pyqtSignal(bool, str)  # 音频服务启动结果信号
    ai_service_started = pyqtSignal(bool)  # AI服务启动结果信号
    all_services_started = pyqtSignal()  # 所有服务启动完成信号

class ServiceInitRunnable(QRunnable):
    """
    服务初始化Runnable，用于在线程池中初始化和启动服务
    """
    def __init__(self, websocket_controller):
        """
        初始化服务初始化Runnable
        
        @param websocket_controller: WebSocket控制器
        """
        super().__init__()
        self.websocket_controller = websocket_controller
        self.logger = Logger.get_logger("service_init_runnable")
        self.port = 8765  # WebSocket服务器端口
        self.signals = ServiceInitSignals()
    
    def run(self):
        """
        Runnable运行方法，初始化和启动所有服务
        """
        self.logger.info("正在线程池中启动所有服务...")
        
        # 启动 WebSocket 服务器
        self._start_websocket_server()
        
        # 启动音频服务
        self._start_audio_service()
        
        # 启动 AI 服务
        self._start_ai_service()
        
        # 短暂延迟，确保所有服务都有足够时间初始化
        time.sleep(0.5)
        
        # 发送所有服务启动完成信号
        self.signals.all_services_started.emit()
        
        self.logger.info("所有服务启动完成")
    
    def _start_websocket_server(self):
        """
        启动WebSocket服务器
        """
        self.logger.info("正在启动WebSocket服务器...")
        
        # 尝试获取WebSocket服务
        from app.services.websocket_service import IWebSocketService
        from app.controllers.websocket_controller import WebSocketController
        
        # 获取WebSocket控制器（应该已经在main.py中初始化好了）
        if not self.websocket_controller:
            self.logger.warning("WebSocket控制器不可用，尝试从ServiceLocator获取")
            self.websocket_controller = ServiceLocator.get(WebSocketController)
        
        # 启动WebSocket服务器
        if self.websocket_controller:
            try:
                success = self.websocket_controller.start_server(self.port)
                if success:
                    self.logger.info(f"WebSocket服务器启动成功，端口: {self.port}")
                else:
                    self.logger.error("WebSocket服务器启动失败")
                # 发送信号
                self.signals.websocket_started.emit(success, self.port)
            except Exception as e:
                self.logger.error(f"启动WebSocket服务器时发生异常: {str(e)}")
                import traceback
                self.logger.error(traceback.format_exc())
                self.signals.websocket_started.emit(False, self.port)
        else:
            self.logger.error("WebSocket控制器不可用，无法启动WebSocket服务器")
            self.signals.websocket_started.emit(False, self.port)
    
    def _start_audio_service(self):
        """
        启动音频服务
        """
        self.logger.info("正在启动音频服务...")
        
        # 获取音频服务并启动
        audio_service = ServiceLocator.get(IAudioService)
        if audio_service:
            try:
                # 检查音频服务是否需要初始化
                if hasattr(audio_service, 'initialize') and callable(getattr(audio_service, 'initialize')):
                    audio_service.initialize()
                    self.logger.info("音频服务已初始化")
                
                # 检查音频服务是否需要启动
                if hasattr(audio_service, 'start') and callable(getattr(audio_service, 'start')):
                    audio_service.start()
                    self.logger.info("音频服务已启动")
                
                self.signals.audio_service_started.emit(True, "已启动")
            except Exception as e:
                self.logger.error(f"启动音频服务失败: {str(e)}")
                import traceback
                self.logger.error(traceback.format_exc())
                self.signals.audio_service_started.emit(False, str(e))
        else:
            self.logger.warning("音频服务不可用，尝试重新获取")
            
            # 尝试重新获取音频服务
            from app.services.audio_service_impl import AudioService
            try:
                audio_service = AudioService()
                ServiceLocator.register(IAudioService, audio_service)
                self.logger.info("已重新创建音频服务")
                self.signals.audio_service_started.emit(True, "已启动")
            except Exception as e:
                self.logger.error(f"创建音频服务失败: {str(e)}")
                self.signals.audio_service_started.emit(False, "服务不可用")
    
    def _start_ai_service(self):
        """启动 AI 服务"""
        self.logger.info("正在启动AI服务...")
        try:
            # 获取 AI 服务
            ai_service = ServiceLocator.get(IAIService)
            if ai_service:
                # 检查AI服务是否需要初始化
                if hasattr(ai_service, 'initialize') and callable(getattr(ai_service, 'initialize')):
                    ai_service.initialize()
                    self.logger.info("AI服务已初始化")
                
                # 检查AI服务是否需要启动
                if hasattr(ai_service, 'start') and callable(getattr(ai_service, 'start')):
                    ai_service.start()
                    self.logger.info("AI服务已启动")
                
                # 添加事件监听
                if hasattr(ai_service, 'add_listener'):
                    # 这些事件监听器会在MainWindow中处理
                    self.logger.info("为AI服务添加事件监听器")
                
                # AI服务初始化成功
                self.logger.info("AI服务启动成功")
                self.signals.ai_service_started.emit(True)
            else:
                self.logger.warning("AI服务不可用，尝试重新获取")
                
                # 尝试重新获取AI服务
                from app.services.ai_service_impl import AIService
                try:
                    ai_service = AIService()
                    ServiceLocator.register(IAIService, ai_service)
                    self.logger.info("已重新创建AI服务")
                    self.signals.ai_service_started.emit(True)
                except Exception as e:
                    self.logger.error(f"创建AI服务失败: {str(e)}")
                    self.signals.ai_service_started.emit(False)
        except Exception as e:
            self.logger.error(f"启动AI服务失败: {str(e)}")
            import traceback
            self.logger.error(traceback.format_exc())
            self.signals.ai_service_started.emit(False)

class MainWindow(QMainWindow):
    """
    主窗口框架类，负责创建基本窗口结构和选项卡
    """
    
    def __init__(self):
        """
        初始化主窗口
        """
        super().__init__()
        
        # 获取日志记录器
        self.logger = Logger.get_logger("main_window")
        
        # 获取WebSocket控制器
        self.websocket_controller = ServiceLocator.get(WebSocketController)
        
        # 设置窗口属性
        self.setWindowTitle("AI直播助手")
        self.resize(1200, 800)
        
        # 初始化 UI
        self._init_ui()
        
        # 应用样式
        self._apply_styles()
        
        # 加载配置到面板
        self._load_config_to_panel()
        
        # 启动所有服务
        self._init_services()
        
        # 注意：不再在这里加载机器人和对话列表，因为这些操作会在服务启动完成后自动执行
        
        self.logger.info("主窗口初始化完成")
    
    def _init_ui(self):
        """
        初始化 UI
        """
        # 创建中央部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 创建主布局
        main_layout = QVBoxLayout(central_widget)
        main_layout.setContentsMargins(10, 10, 10, 10)
        main_layout.setSpacing(10)
        
        # 创建主选项卡
        self.main_tabs = QTabWidget()
        self.main_tabs.setTabPosition(QTabWidget.North)
        self.main_tabs.setTabShape(QTabWidget.Rounded)
        main_layout.addWidget(self.main_tabs)
        
        # 创建中控、配置和视频号面板
        self.control_panel = ControlPanel()
        self.config_panel = ConfigPanel()
        self.channel_panel = ChannelPanel()
        
        # 添加到选项卡
        self.main_tabs.addTab(self.control_panel, "中控")
        self.main_tabs.addTab(self.config_panel, "配置")
        self.main_tabs.addTab(self.channel_panel, "视频号")
        
        # 连接配置面板的信号
        self.config_panel.config_updated.connect(self._on_config_updated)
        
        # 连接视频号面板的信号
        self.channel_panel.config_updated.connect(self._on_config_updated)
        
        # 初始化 AI 服务状态为"未启用"
        self.control_panel.update_ai_service_status("未连接")
    
    def _apply_styles(self):
        """
        应用样式
        """
        # 设置选项卡样式
        self.main_tabs.setStyleSheet("""
            QTabWidget::pane {
                border: 1px solid #ddd;
                border-radius: 3px;
                background-color: #fff;
            }
            QTabBar::tab {
                background-color: #f5f5f5;
                border: 1px solid #ddd;
                border-bottom: none;
                border-top-left-radius: 3px;
                border-top-right-radius: 3px;
                padding: 8px 12px;
                margin-right: 2px;
                color: #666;
                font-weight: normal;
            }
            QTabBar::tab:selected {
                background-color: #fff;
                border-bottom: 2px solid #2196F3;
                color: #2196F3;
                font-weight: bold;
            }
            QTabBar::tab:hover:!selected {
                background-color: #e6e6e6;
                border-bottom: 1px solid #ccc;
            }
        """)
    
    # 以下是代理方法，将调用转发到相应的面板
    
    def add_interaction(self, username, content):
        """添加用户互动"""
        self.control_panel.add_interaction(username, content)
    
    def add_user_join(self, username, count):
        """添加用户进入"""
        self.control_panel.add_user_join(username, count)
    
    def add_to_playlist(self, item_type, content):
        """添加项目到播放队列"""
        self.control_panel.add_to_playlist(item_type, content)
    
    def add_playback_log(self, message):
        """添加播放日志"""
        self.control_panel.add_playback_log(message)
    
    def add_ai_log(self, message):
        """添加AI回复日志"""
        self.control_panel.add_ai_log(message)
    
    def add_sync_item(self, speech, video, keyword):
        """添加音画同步项目"""
        self.control_panel.add_sync_item(speech, video, keyword)
    
    def update_connection_status(self, status):
        """更新连接状态"""
        self.control_panel.update_connection_status(status)
    
    def update_host_status(self, status):
        """更新主播状态"""
        self.control_panel.update_host_status(status)
    
    def update_playback_status(self, status):
        """更新播放状态"""
        self.control_panel.update_playback_status(status)
    
    def update_audio_service_status(self, status):
        """更新音频服务状态"""
        self.control_panel.update_audio_service_status(status)
    
    def update_sync_status(self, status):
        """更新音画同步状态"""
        self.control_panel.update_sync_status(status)
    
    def update_playback_info(self, info):
        """更新播放信息"""
        self.control_panel.update_playback_info(info)
    
    def update_generated_info(self, info):
        """更新生成信息"""
        self.control_panel.update_generated_info(info)
    
    def _on_config_updated(self, config_name, value):
        """处理配置更新事件"""
        self.logger.debug(f"配置更新: {config_name} = {value}")
        
        # 获取配置服务
        config_service = ServiceLocator.get(IConfigService)
        
        # 处理 AI 相关配置
        if config_name == "token":
            # 更新Token
            if value:
                self.logger.info(f"更新Token: {value[:5]}...")
                
                # 更新AI服务配置
                ai_service = ServiceLocator.get(IAIService)
                if ai_service:
                    ai_service.configure({"token": value})
                    
                    # 保存到配置并持久化
                    if config_service:
                        config_service.set("ai.token", value)
                        config_service.save_config()  # 确保token被持久化保存
                        self.logger.info("Token已保存到配置文件")
                    
                    # 获取机器人列表
                    try:
                        bots = ai_service.get_bots()
                        if bots:
                            self.logger.info(f"成功获取到 {len(bots)} 个机器人")
                            self.config_panel.update_bot_list(bots)
                        else:
                            self.logger.warning("未获取到任何机器人")
                            show_toast(self, "未获取到任何机器人，请检查Token是否正确", 3000, Toast.WARNING)
                    except Exception as e:
                        self.logger.error(f"获取机器人列表失败: {str(e)}")
                        show_toast(self, f"获取机器人列表失败: {str(e)}", 3000, Toast.ERROR)
        elif config_name == "audio_output":
            self.control_panel.update_audio_output_status(value)
            # 保存到配置
            if config_service:
                config_service.set("audio.output", value)
                config_service.save_config()
        elif config_name == "audio_service_status":
            self.control_panel.update_audio_service_status(value)
        elif config_name == "tts_url":
            # 更新TTS URL配置
            if config_service:
                config_service.set("tts.url", value)
                config_service.save_config()
                
                # 更新音频服务配置
                audio_service = ServiceLocator.get(IAudioService)
                if audio_service:
                    audio_service.configure({"tts_url": value})
                    self.logger.info(f"已更新TTS服务URL: {value}")
        elif config_name == "keyword_status":
            self.control_panel.update_keyword_status(value)
        elif config_name == "user_join_status":
            self.control_panel.update_user_join_status(value)
        # 处理流量欢迎配置
        elif config_name.startswith("flow_welcome."):
            # 保存到配置
            if config_service:
                config_service.set(config_name, value)
                config_service.save_config()
                
                # 更新流量监控服务配置
                from app.services.flow_monitor_service import IFlowMonitorService
                flow_monitor_service = ServiceLocator.get(IFlowMonitorService)
                if flow_monitor_service:
                    # 提取配置项名称
                    config_key = config_name.split(".")[-1]
                    # 更新流量监控服务配置
                    flow_monitor_service.configure({config_key: value})
                    self.logger.info(f"已更新流量欢迎配置: {config_key}={value}")
                    
                    # 调用重载配置方法确保配置立即生效
                    if hasattr(flow_monitor_service, 'reload_config'):
                        result = flow_monitor_service.reload_config()
                        if result:
                            self.logger.info("已重载流量监控服务配置")
                        else:
                            self.logger.warning("流量监控服务配置重载失败")
                else:
                    self.logger.warning(f"流量监控服务不存在，无法更新配置: {config_name}={value}")
                    
                # 通知控制面板更新动态欢迎状态
                if hasattr(self, 'control_panel') and self.control_panel:
                    # 确保control_panel有更新状态的方法
                    if hasattr(self.control_panel, '_update_flow_welcome_status'):
                        # self.logger.debug(f"通知控制面板更新动态欢迎状态，配置{config_name}已变更为{value}")
                        # 立即更新
                        self.control_panel._update_flow_welcome_status()
                        # 延迟500ms后再次更新，确保配置已完全保存和应用
                        QTimer.singleShot(500, self.control_panel._update_flow_welcome_status)
        elif config_name == "bot_id":
            # 更新机器人ID
            if isinstance(value, dict):
                bot_id = value.get("bot_id")
                display_name = value.get("display_name")
                
                if bot_id:
                    self.logger.info(f"更新 bot_id: {bot_id}")
                    
                    # 更新AI服务配置
                    ai_service = ServiceLocator.get(IAIService)
                    if ai_service:
                        ai_service.configure({"bot_id": bot_id})
                        
                        # 保存到配置
                        if config_service:
                            config_service.set("ai.bot_id", bot_id)
                            if display_name:
                                config_service.set("ai.last_bot_name", display_name)
                                self.logger.info(f"保存机器人名称: {display_name}")
            else:
                self.logger.warning(f"无效的bot_id值: {value}")
        elif config_name == "create_conversation":
            # 创建新会话
            bot_id = value
            if bot_id:
                self.logger.info(f"为机器人 {bot_id} 创建新会话")
                
                try:
                    # 获取机器人名称
                    bot_name = config_service.get("ai.last_bot_name", "未知机器人")
                    self.logger.info(f"当前机器人名称: {bot_name}")
                    
                    # 创建新会话
                    ai_service = ServiceLocator.get(IAIService)
                    if ai_service:
                        conversation_id = ai_service.create_conversation()
                        if conversation_id:
                            self.logger.info(f"创建会话成功，ID: {conversation_id}")
                            
                            # 更新AI服务配置
                            ai_service.configure({"conversation_id": conversation_id})
                            
                            # 在AI回复日志中输出信息
                            self.add_ai_log(f"{bot_name} - 会话ID({conversation_id})")
                            
                            # 显示成功提示
                            show_toast(self, "创建会话成功", 2000, Toast.SUCCESS)
                        else:
                            self.logger.warning("创建会话失败，返回的ID为空")
                            show_toast(self, "创建会话失败", 3000, Toast.ERROR)
                except Exception as e:
                    self.logger.error(f"创建会话失败: {str(e)}")
                    show_toast(self, f"创建会话失败: {str(e)}", 3000, Toast.ERROR)
        elif config_name == "stream_mode":
            # 更新流式对话模式
            stream_mode = value
            self.logger.info(f"更新流式对话模式: {stream_mode}")
            
            # 更新AI服务配置
            ai_service = ServiceLocator.get(IAIService)
            if ai_service:
                ai_service.configure({"stream_mode": stream_mode})
                
                # 保存到配置
                if config_service:
                    config_service.set("ai.stream_mode", stream_mode)
                    config_service.save_config()
        elif config_name == "keyword_min":
            # 保存到配置
            if config_service:
                config_service.set("keyword.min", value)
                config_service.save_config()
        elif config_name == "keyword_max":
            # 保存到配置
            if config_service:
                config_service.set("keyword.max", value)
                config_service.save_config()
        elif config_name == "user_join_min":
            # 保存到配置
            if config_service:
                config_service.set("user_join.min", value)
                config_service.save_config()
        elif config_name == "user_join_max":
            # 保存到配置
            if config_service:
                config_service.set("user_join.max", value)
                config_service.save_config()
        elif config_name == "audio_volume":
            # 保存到配置
            if config_service:
                config_service.set("audio.volume", value)
                config_service.save_config()
        elif config_name == "host_voice":
            # 保存到配置
            if config_service:
                config_service.set("speech.host_voice", value)
                config_service.save_config()
        elif config_name == "assist_voice":
            # 保存到配置
            if config_service:
                config_service.set("speech.assist_voice", value)
                config_service.save_config()
        elif config_name == "host_speed":
            # 保存到配置
            if config_service:
                config_service.set("speech.host_speed", value)
                config_service.save_config()
        elif config_name == "assist_speed":
            # 保存到配置
            if config_service:
                config_service.set("speech.assist_speed", value)
                config_service.save_config()
        elif config_name == "reverb":
            # 保存到配置
            if config_service:
                config_service.set("audio.reverb", value)
                config_service.save_config()
        elif config_name == "add_pt_suffix":
            # 保存到配置
            if config_service:
                config_service.set("speech.add_pt_suffix", value)
                config_service.save_config()
                
                # 通知语音服务更新配置
                speech_service = ServiceLocator.get(ISpeechService)
                if speech_service:
                    speech_service.configure({"add_pt_suffix": value})
        elif config_name == "keyword_enabled":
            # 保存到配置
            if config_service:
                config_service.set("keyword.enabled", value)
                config_service.save_config()
            
            # 更新控制面板中的状态
            self.control_panel.keyword_enabled = value
            # 重新触发状态更新，以应用正确的颜色
            keyword_min = config_service.get("keyword.min", 30)
            keyword_max = config_service.get("keyword.max", 60)
            self.control_panel.update_keyword_status(f"{keyword_min}-{keyword_max}秒")
            
            # 更新音频服务配置
            audio_service = ServiceLocator.get(IAudioService)
            if audio_service:
                # 获取配置路径
                config_path = config_service.get("app.config_path", "")
                if config_path:
                    # 配置音频服务，传递关键词启用状态
                    try:
                        audio_service.configure({
                            "config_path": config_path,
                            "keyword_enabled": value
                        })
                        self.logger.info(f"已重新配置音频服务，关键词功能: {'启用' if value else '禁用'}")
                    except Exception as e:
                        self.logger.error(f"重新配置音频服务失败: {str(e)}")
                        import traceback
                        self.logger.error(traceback.format_exc())
                else:
                    self.logger.warning("配置路径为空，无法重新配置音频服务")
        elif config_name == "user_join_enabled":
            # 保存到配置
            if config_service:
                config_service.set("user_join.enabled", value)
                config_service.save_config()
                
            # 更新控制面板中的状态
            self.control_panel.user_join_enabled = value
            # 重新触发状态更新，以应用正确的颜色
            user_join_min = config_service.get("user_join.min", 30)
            user_join_max = config_service.get("user_join.max", 60)
            self.control_panel.update_user_join_status(f"{user_join_min}-{user_join_max}秒")
        elif config_name == "config_path":
            # 保存配置路径
            if config_service:
                config_service.set("app.config_path", value)
                config_service.save_config()
                self.logger.info(f"已更新配置路径: {value}")
        elif config_name == "refresh_config":
            # 从指定路径刷新配置
            if config_service:
                try:
                    # 尝试从指定路径加载配置
                    success = config_service.load_config_from_path(value)
                    if success:
                        # 重新加载配置到面板
                        self._load_config_to_panel()
                        show_toast(self, "成功", "配置已成功刷新", Toast.SUCCESS)
                        self.logger.info(f"已从路径刷新配置: {value}")
                    else:
                        show_toast(self, "错误", "配置刷新失败，请检查配置文件是否有效", Toast.ERROR)
                        self.logger.error(f"配置刷新失败: {value}")
                except Exception as e:
                    show_toast(self, "错误", f"配置刷新失败: {str(e)}", Toast.ERROR)
                    self.logger.error(f"配置刷新异常: {str(e)}")
    
    def _show_connection_success_toast(self):
        """
        显示连接成功的 Toast 提示
        """
        self.logger.info("显示 Toast 提示：连接成功")
        toast = show_toast(self, "连接成功", 3000, Toast.SUCCESS)
        QApplication.processEvents()  # 确保 Toast 显示在最前面
    
    def _show_test_toast(self):
        """
        显示测试 Toast 提示
        """
        self.logger.info("显示测试 Toast 提示")
        toast = show_toast(self, "这是一个测试 Toast 提示", 3000, Toast.SUCCESS)
        QApplication.processEvents()  # 确保 Toast 显示在最前面
    
    def _init_services(self):
        """
        启动所有服务
        
        使用QRunnable和QThreadPool在后台线程中初始化和启动所有服务，
        避免阻塞主线程，提高应用程序响应性
        """
        self.logger.info("准备启动所有服务...")
        
        # 创建服务初始化Runnable
        service_init_runnable = ServiceInitRunnable(self.websocket_controller)
        
        # 连接信号
        service_init_runnable.signals.websocket_started.connect(self._on_websocket_started)
        service_init_runnable.signals.audio_service_started.connect(self._on_audio_service_started)
        service_init_runnable.signals.ai_service_started.connect(self._on_ai_service_started)
        service_init_runnable.signals.all_services_started.connect(self._on_all_services_started)
        
        # 启动Runnable
        QThreadPool.globalInstance().start(service_init_runnable)
        
        self.logger.info(f"服务初始化任务已提交到线程池，当前线程池活动线程数: {QThreadPool.globalInstance().activeThreadCount()}")
    
    def _on_websocket_started(self, success, port):
        """
        处理WebSocket服务器启动结果
        
        @param success: 是否成功启动
        @param port: 端口号
        """
        if success:
            self.logger.info(f"WebSocket服务器已启动，地址：0.0.0.0:{port}")
            self.control_panel.update_connection_status("未连接")
            self.control_panel.log_panel.add_playback_log(f"WebSocket服务器已启动，地址：0.0.0.0:{port}")
            # 显示提示信息
            self.control_panel.log_panel.add_playback_log(f"请在socket_debugger中连接到 ws://[本机IP]:{port}")
        else:
            self.logger.error("启动WebSocket服务器失败")
            self.control_panel.update_connection_status("服务器错误")
            self.control_panel.log_panel.add_playback_log("启动WebSocket服务器失败")
            
            # 显示错误消息（使用Toast，自动消失）
            show_toast(self, "启动WebSocket服务器失败，请检查端口是否被占用", 5000, Toast.ERROR)
    
    def _on_audio_service_started(self, success, message):
        """
        处理音频服务启动结果
        
        @param success: 是否成功启动
        @param message: 消息
        """
        if success:
            # 音频服务启动成功，但连接状态由TTS服务检测决定
            self.control_panel.log_panel.add_playback_log("音频服务已启动")
            # 不再直接设置状态，而是等待TTS连接检测结果
        else:
            self.control_panel.update_audio_service_status("启动失败")
            self.control_panel.log_panel.add_playback_log(f"启动音频服务失败: {message}")
    
    def _on_ai_service_started(self, success):
        """
        处理AI服务启动结果
        
        @param success: 是否成功启动
        """
        if success:
            self.logger.info("AI服务启动成功")
            # 检查是否有有效的会话ID
            ai_service = ServiceLocator.get(IAIService)
            if ai_service and ai_service._config.get("conversation_id"):
                self.control_panel.update_ai_service_status("已连接")
            else:
                self.control_panel.update_ai_service_status("未连接")
        else:
            self.logger.error("AI服务启动失败")
            self.control_panel.update_ai_service_status("连接失败")
    
    def _on_all_services_started(self):
        """
        处理所有服务启动完成
        
        当所有服务启动完成后，更新UI状态，加载机器人和对话列表
        """
        self.logger.info("所有服务已启动完成")
        self.control_panel.log_panel.add_playback_log("所有服务已启动完成")
        
        # 添加音频服务状态变化事件监听
        audio_service = ServiceLocator.get(IAudioService)
        if audio_service:
            # 先移除可能存在的旧监听器，避免重复
            audio_service.remove_listener("audio_service_status_changed", self._on_audio_service_status_changed)
            # 添加新监听器
            audio_service.add_listener("audio_service_status_changed", self._on_audio_service_status_changed)
            
            # 立即检查TTS连接状态并更新UI
            if hasattr(audio_service, '_check_tts_connection'):
                is_connected = audio_service._check_tts_connection()
                self.control_panel.update_audio_service_status("已连接" if is_connected else "未连接")
        
        # 添加AI服务会话创建事件监听
        ai_service = ServiceLocator.get(IAIService)
        if ai_service:
            # 先移除可能存在的旧监听器，避免重复
            ai_service.remove_listener("conversation_created", self._on_conversation_created)
            # 添加新监听器
            ai_service.add_listener("conversation_created", self._on_conversation_created)
            
            # 检查是否已有会话，有则更新状态为已连接
            if ai_service._config.get("conversation_id"):
                self.control_panel.update_ai_service_status("已连接")
                self.logger.info("检测到现有会话ID，更新AI服务状态为已连接")
                
        # 确保关键词话术管理器被正确初始化
        config_service = ServiceLocator.get(IConfigService)
        if config_service:
            keyword_enabled = config_service.get("keyword.enabled", False)
            if keyword_enabled:
                config_path = config_service.get("app.config_path", "")
                if config_path and audio_service and not hasattr(audio_service, 'keyword_speech_manager'):
                    self.logger.info("关键词功能已启用但管理器未初始化，尝试初始化")
                    try:
                        audio_service.configure({
                            "config_path": config_path,
                            "keyword_enabled": True
                        })
                        self.logger.info("关键词话术管理器初始化成功")
                    except Exception as e:
                        self.logger.error(f"初始化关键词话术管理器失败: {str(e)}")
        
        # 确保流量监控服务配置正确加载
        from app.services.flow_monitor_service import IFlowMonitorService
        flow_monitor_service = ServiceLocator.get(IFlowMonitorService)
        if flow_monitor_service and hasattr(flow_monitor_service, 'reload_config'):
            try:
                self.logger.info("重新加载流量监控服务配置...")
                result = flow_monitor_service.reload_config()
                if result:
                    self.logger.info("流量监控服务配置已重新加载")
                else:
                    self.logger.warning("流量监控服务配置重新加载失败")
            except Exception as e:
                self.logger.error(f"重新加载流量监控服务配置时出错: {str(e)}")
                import traceback
                self.logger.error(traceback.format_exc())
        
        # 显示成功提示（使用Toast，自动消失，无声音）
        show_toast(self, "所有服务已成功启动，应用程序准备就绪", 3000, Toast.SUCCESS)
        
        # 加载机器人和对话列表
        self._trigger_bot_and_conversation_loading()
        
        # 获取AI服务和配置服务
        ai_service = ServiceLocator.get(IAIService)
        config_service = ServiceLocator.get(IConfigService)
        
        if ai_service and config_service:
            bot_id = config_service.get("ai.bot_id")
            conversation_id = config_service.get("ai.conversation_id")
            bot_name = config_service.get("ai.last_bot_name", "未知机器人")
            
            # 如果有机器人ID但没有会话ID，创建一个初始会话
            if bot_id and not conversation_id:
                self.logger.info(f"为机器人 {bot_id} 创建初始会话")
                try:
                    # 创建新会话
                    conversation_id = ai_service.create_conversation()
                    if conversation_id:
                        self.logger.info(f"创建初始会话成功，ID: {conversation_id}")
                        
                        # 更新AI服务配置
                        ai_service.configure({"conversation_id": conversation_id})
                        
                        # 在AI回复日志中输出信息
                        self.add_ai_log(f"{bot_name} - 会话ID({conversation_id})")
                except Exception as e:
                    self.logger.error(f"创建初始会话失败: {str(e)}")
            # 如果已经有会话ID，显示当前会话信息
            elif bot_id and conversation_id:
                self.logger.info(f"使用现有会话，ID: {conversation_id}")
                # 在AI回复日志中输出信息
                self.add_ai_log(f"{bot_name} - 会话ID({conversation_id})")

    def _load_bots(self):
        """
        加载机器人列表
        """
        # 获取配置服务
        config_service = ServiceLocator.get(IConfigService)
        if not config_service:
            self.logger.error("无法获取配置服务")
            return
        
        # 获取 AI 配置
        ai_config = config_service.get("ai", {})
        
        # 获取 AI 服务
        ai_service = ServiceLocator.get(IAIService)
        if not ai_service:
            self.logger.error("无法获取 AI 服务")
            return
        
        # 如果有 token，主动获取机器人列表（不显示Toast）
        token = ai_config.get("token")
        if token:
            self.logger.info(f"开始加载机器人列表，使用token: {token[:5]}...")
            try:
                # 确保AI服务已配置token，但不重新初始化服务
                # 只更新token配置，不触发完整的服务初始化
                current_config = ai_service._config.copy() if hasattr(ai_service, '_config') else {}
                if current_config.get("token") != token:
                    current_config["token"] = token
                    ai_service.configure(current_config)
                
                # 获取机器人列表
                bots = ai_service.get_bots()
                if bots:
                    self.logger.info(f"成功获取到 {len(bots)} 个机器人")
                    self.config_panel.update_bot_list(bots)
                else:
                    self.logger.warning("未获取到任何机器人")
            except Exception as e:
                self.logger.error(f"加载机器人列表失败: {str(e)}")
                # 不显示Toast提示错误

    def _load_config_to_panel(self):
        """
        从配置服务中加载配置并应用到配置面板
        """
        try:
            # 获取配置服务
            config_service = ServiceLocator.get(IConfigService)
            if not config_service:
                self.logger.error("无法获取配置服务")
                return
            
            # 获取配置路径
            config_path = config_service.get("app.config_path", "")
            
            # 获取 AI 配置
            ai_config = config_service.get("ai", {})
            
            # 获取音频配置
            audio_config = config_service.get("audio", {})
            
            # 获取语音配置
            speech_config = config_service.get("speech", {})
            
            # 获取关键词和用户加入配置
            keyword_min = config_service.get("keyword.min", 5)
            keyword_max = config_service.get("keyword.max", 10)
            user_join_min = config_service.get("user_join.min", 5)
            user_join_max = config_service.get("user_join.max", 10)
            keyword_enabled = config_service.get("keyword.enabled", True)
            user_join_enabled = config_service.get("user_join.enabled", True)
            
            # 应用 AI 配置到配置面板
            try:
                # 设置配置路径
                self.config_panel.set_config_path(config_path)
                
                # 调用配置面板的load_config方法加载全部配置
                self.config_panel.load_config()
                
                # 设置 AI 配置
                self.config_panel.set_ai_config(ai_config)
                
                # 检查是否已经选择了会话，如果是，则更新 AI 服务状态为"已连接"
                if "conversation_id" in ai_config and ai_config["conversation_id"]:
                    self.control_panel.update_ai_service_status("已连接")
                    self.logger.info("AI 服务已连接")
                else:
                    self.control_panel.update_ai_service_status("未连接")
                    self.logger.info("AI 服务未连接")
                
                # 设置音频配置
                self.config_panel.set_audio_config(audio_config)
                
                # 设置语音配置
                self.config_panel.set_speech_config(speech_config)
                
                # 设置关键词和用户加入配置
                self.config_panel.set_keyword_user_config(
                    keyword_min, keyword_max, 
                    keyword_enabled
                )
                
                # 加载视频号面板配置
                # 由于视频号面板有自己的load_config方法，所以直接调用即可
                self.channel_panel.load_config()
                
                self.logger.info("已加载配置到所有面板")
            except Exception as e:
                self.logger.error(f"应用配置失败: {str(e)}")
                import traceback
                self.logger.error(traceback.format_exc())
        except Exception as e:
            self.logger.error(f"加载配置到面板失败: {str(e)}")

    def _on_audio_service_status_changed(self, event):
        """
        处理音频服务状态变化事件
        
        @param event: 事件对象
        """
        status = event.data
        self.logger.info(f"音频服务状态变化: {status}")
        self.control_panel.update_audio_service_status(status)

    def closeEvent(self, event):
        """
        窗口关闭事件处理
        
        @param event: 关闭事件
        """
        # 关闭WebSocket服务器
        if self.websocket_controller:
            self.websocket_controller.stop_server()
        
        # 关闭视频号模块的自动检测
        if hasattr(self, 'channel_panel') and hasattr(self.channel_panel, 'channel_module'):
            try:
                self.channel_panel.channel_module.shutdown()
                self.logger.info("已关闭视频号模块")
            except Exception as e:
                self.logger.error(f"关闭视频号模块失败: {str(e)}")
            
        self.logger.info("程序退出")
        super().closeEvent(event)

    def _trigger_bot_and_conversation_loading(self):
        """
        主动触发机器人列表加载（不显示Toast）
        """
        # 获取配置服务
        config_service = ServiceLocator.get(IConfigService)
        if not config_service:
            self.logger.warning("无法获取配置服务，跳过加载机器人列表")
            return
        
        # 获取AI服务
        ai_service = ServiceLocator.get(IAIService)
        if not ai_service:
            self.logger.warning("无法获取AI服务，跳过加载机器人列表")
            return
        
        # 获取Token
        token = config_service.get("ai.token")
        if not token:
            self.logger.warning("未配置Token，跳过加载机器人列表")
            return
        
        # 显示Token前几位字符，隐藏其余部分
        visible_token = token[:5] + "..."
        self.logger.info(f"开始加载机器人列表，使用token: {visible_token}")
        
        try:
            # 获取机器人列表
            bots = ai_service.get_bots()
            if not bots:
                self.logger.warning("未获取到机器人列表")
                return
            
            self.logger.info(f"成功获取到 {len(bots)} 个机器人")
            
            # 更新AI配置模块
            self.config_panel.ai_config_module.update_bot_list(bots)
            
            # 获取保存的机器人ID
            saved_bot_id = config_service.get("ai.bot_id")
            
            # 如果有保存的机器人ID，选择它
            if saved_bot_id:
                for bot in bots:
                    if bot.get("id") == saved_bot_id:
                        self.config_panel.ai_config_module.select_bot(saved_bot_id)
                        break
        except Exception as e:
            self.logger.error(f"加载机器人列表失败: {str(e)}")
            import traceback
            self.logger.error(traceback.format_exc())

    def _on_conversation_created(self, event):
        """
        处理AI服务会话创建事件
        
        @param event: 事件对象
        """
        try:
            data = event.data
            if not data or not isinstance(data, dict):
                self.logger.warning(f"收到无效的会话创建事件数据: {data}")
                return
                
            conversation_id = data.get("conversation_id")
            name = data.get("name", "未命名会话")
            
            if not conversation_id:
                self.logger.warning("会话创建事件中没有会话ID")
                return
                
            self.logger.info(f"检测到新会话创建: ID={conversation_id}, 名称={name}")
            
            # 更新AI服务状态为已连接
            self.control_panel.update_ai_service_status("已连接")
            self.logger.info("更新AI服务状态为已连接")
            
            # 在AI回复日志中输出信息
            # 获取机器人名称
            ai_service = ServiceLocator.get(IAIService)
            config_service = ServiceLocator.get(IConfigService)
            
            if ai_service and config_service:
                bot_id = ai_service._config.get("bot_id")
                bot_name = config_service.get("ai.last_bot_name", "未知机器人")
                self.add_ai_log(f"{bot_name} - 会话ID({conversation_id})")
            else:
                self.add_ai_log(f"新会话 - ID({conversation_id})")
        except Exception as e:
            self.logger.error(f"处理会话创建事件失败: {str(e)}")
            import traceback
            self.logger.error(traceback.format_exc()) 